#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    serialPortInit();
    ui->progressBar->setValue(0);
    ui->progressBar->setRange(0,100);


}

MainWindow::~MainWindow()
{
    delete ui;
}




void MainWindow::on_btnOpenCom_clicked(bool)
{
    if(ui->btnOpenCom->text() == "打开串口"){
        serialPort->setPortName(ui->comBox->currentText());
        serialPort->setBaudRate(115200);
        serialPort->setDataBits(QSerialPort::Data8);
        serialPort->setParity(QSerialPort::NoParity);
        serialPort->setStopBits(QSerialPort::OneStop);
        /* 设置停止位 */
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
        if(!serialPort->open(QIODevice::ReadWrite))
        {
            QMessageBox::about(NULL,"错误","串口无法打开！可能串口已经被占用");
            qDebug()<<"name: "<<serialPort->portName()<<" error: "<<serialPort->errorString()<<endl;
        }
        else{
            ui->comBox->setEnabled(false);
            ui->btnOpenCom->setText("关闭串口");
            serialPort->write("hello mcu",9);
        }
    }else{
        serialPort->close();
        ui->comBox->setEnabled(true);
        ui->btnOpenCom->setText("打开串口");
    }
}

void MainWindow::serialPortInit()
{
    serialPort = new QSerialPort(this);
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        this->ui->comBox->addItem(info.portName());
    }
    ui->btnOpenCom->setText("打开串口");
    connect(serialPort,SIGNAL(readyRead()),this,SLOT(serialPortReadyRead()));

    serialTimer = new QTimer(this);
    serialTimer->setSingleShot(true);
    connect(serialTimer,&QTimer::timeout,this,&MainWindow::serialTimerTimeoutHandle);
}

void MainWindow::on_btnOpenFile_clicked(bool)
{
   // 使用 QFileDialog 获取文件路径
   updateFilePath = QFileDialog::getOpenFileName(
       this,
       "选择固件文件",          // 对话框标题
       "",                    // 默认打开路径（空表示系统默认）
       "所有文件 (*.*)"        // 文件过滤器
   );

   if (!updateFilePath.isEmpty()) {
       // 这里可以添加文件路径处理逻辑
       qDebug() << "已选择文件:" << updateFilePath;
   }

}

void MainWindow::on_btnDownLoad_clicked(bool)
{
    if(this->updateFilePath.isEmpty())
    {
        QMessageBox::about(NULL,"错误","请先选择升级文件");
        return;
    }

    // 修正1：添加文件对象定义和打开操作
//    QFile file(updateFilePath);
    sendFile = new QFile(updateFilePath);
    if (!sendFile->open(QIODevice::ReadOnly)) {
        QMessageBox::about(NULL, "错误", "无法打开文件");
        return;
    }

    if(!serialPort->isOpen())
    {
        QMessageBox::about(NULL,"错误","请先打开串口");
        return;
    }

//    const int chunkSize = 1024; // 1KB分块
//    qint64 totalBytes = sendFile->size();
//    qint64 bytesSent = 0;


    bytesRemaining = sendFile->size();
    bytesFileSize = bytesRemaining;
    sendDataTimer = new QTimer(this);
    connect(sendDataTimer, &QTimer::timeout, this, [this]() {
        const int chunkSize = 1024;
        QByteArray chunk = sendFile->read(chunkSize);

        if(!chunk.isEmpty()) {
            serialPort->write(chunk);
            bytesRemaining -= chunk.size();
            qDebug() << "剩余字节:" << bytesRemaining;
            // ui->progressBar->setValue(((bytesFileSize - bytesRemaining)/bytesFileSize)*100);
            ui->progressBar->setValue(qRound(static_cast<double>(bytesFileSize - bytesRemaining)/bytesFileSize * 1000.0)/10.0);
            // update();
            // sha256_update(&ctx, text3, chunkSize);
            sha256_update(&ctx, reinterpret_cast<BYTE*>(chunk.data()), chunk.size());
        }

        if(bytesRemaining <= 0) {
            sendDataTimer->stop();
            sendFile->close();
            QMessageBox::about(NULL, "完成", "文件发送完毕");
            BYTE buf[SHA256_BLOCK_SIZE];
            sha256_final(&ctx, buf);


            // 将二进制哈希值转换为HEX字符串
            QByteArray hashBytes(reinterpret_cast<char*>(buf), SHA256_BLOCK_SIZE);
            QString hexHash = hashBytes.toHex().toUpper();
            qDebug() << "SHA256哈希值:" << hexHash;

            QByteArray hexBytes = hexHash.toLatin1();
            const int blockSize = 32; // 分块大小（根据RSA密钥长度调整）
            unsigned int cw[64] = {0}; // 需要两倍空间存储加密结果
            char signature[64] = {0};
            // 分块加密
            for(int i=0; i<2; i++) {
                rsa_encrypt(priv, 
                    hexBytes.data() + i*blockSize,  // 数据偏移
                    blockSize,                      // 每块长度
                    cw + i*blockSize);              // 输出偏移
            }

            // 分块解密
            for(int i=0; i<2; i++) {
                rsa_decrypt(pub, 
                    cw + i*blockSize,    // 密文偏移
                    blockSize,          // 每块长度
                    signature + i*blockSize); // 输出偏移
            }

            bool verifyOK = true;
            for(int i = 0; i < SHA256_BLOCK_SIZE; i++) {
                if(hexBytes[i] != signature[i]) {
                    verifyOK = false;
                    break;
                }
            }

            if(verifyOK) {
                qDebug() << "签名验证成功";
                QMessageBox::about(NULL, "成功", "签名验证通过");
            } else {
                qDebug() << "签名验证失败";
                QMessageBox::about(NULL, "错误", "签名验证失败");
            }
        
        }
    });

    sendDataTimer->start(100); // 严格每100ms触发一次
    sha256_init(&ctx);



    pub = { 0,0 };
    priv = { 0 ,0};
    rsa_gen_keys(&pub, &priv);


	//generate rand serils num 
	// generate_rand(mv, len);
   


	// rsa_encrypt(priv, mv, len, cw);

	// rsa_decrypt(pub, cw, len, mv_t);
	
	// for(i=0;i<len;i++)
	// {
	// 	if(mv[i]!=mv_t[i])
	// 		return -1;
	// }

	// return 0;

}

void MainWindow::serialPortReadyRead()
{
    serialTimer->start(50);
}

void MainWindow::serialTimerTimeoutHandle( )
{

    QByteArray buf = serialPort->readAll();
    // 自动判断内容类型
    if(isPrintableAscii(buf)) {
        // 可读文本直接转换
        QString text = QString::fromUtf8(buf).trimmed();
        ui->textBrowser->append(text + "\n");  // 添加换行
    } else {
        // 二进制数据转HEX格式显示
        QString hexText = buf.toHex(' ').toUpper();
        ui->textBrowser->append("[HEX] " + hexText + "\n");
    }

//    qDebug() << "read buf:" << buf;

}

bool MainWindow::isPrintableAscii(const QByteArray &data) {
    for(char c : data) {
        // 允许空格(32)到波浪号(126)的标准ASCII可打印字符
        if(static_cast<unsigned char>(c) < 32 ||
           static_cast<unsigned char>(c) > 126) {
            return false;
        }
    }
    return !data.isEmpty();
}

